home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / source / demostu2 / dotcube2.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-12-15  |  7.6 KB  |  367 lines

  1. PROGRAM dotcube2;
  2. {
  3.   Dotcube2
  4.   - by Bjarke Viksφe
  5.   aug 1994
  6.  
  7.   Screen mode is 320x200x16.
  8.   Buffer in made 256 bytes wide, so we can address (x,y) fast.
  9.   When box is drawn, buffer is copied to display screen.
  10.   Plots 3072 dots, when it's doing 3 faces!
  11.   Notice that only 8 coords are actually rotated. The rest are based
  12.   on those 8 plots.
  13.   I take 2 opposite lines in each face and split them into
  14.   16 parts. And dotted lines (16 dots pr. line) are then drawn between
  15.   each new line that comes out of the split.
  16.   Try to fiddle with the "NUMBER_SPLITS" value to see how many you can
  17.   get. On my 40Mhz '486 I can get around 17000 dots at 70 fps.
  18.   And it can still be optimized. Unroll a few loops and you'll see...
  19. }
  20.  
  21. {$A+,B-,G+,E+,I+,N-,X+}
  22. {$C FIXED PRELOAD PERMANENT}
  23.  
  24.  
  25. USES
  26.     DEMOINIT;
  27.  
  28. {$DEFINE DEBUG}
  29.  
  30. CONST
  31.     NUMBER_FACES = 6;
  32.     NUMBER_COORDS = 8;
  33.     BOX = 110; {size of box}
  34.     NUMBER_SPLITS = 32; {number of pieces each line is broken into}
  35.  
  36. TYPE
  37.     facetype = RECORD
  38.         l1,l2,l3,l4 : byte;
  39.     end;
  40.     slopearray = array[0..NUMBER_SPLITS] of integer;
  41.  
  42. VAR
  43.     SlopeX1 : slopearray;
  44.     SlopeY1 : slopearray;
  45.     SlopeX2 : slopearray;
  46.     SlopeY2 : slopearray;
  47.     face : array[1..NUMBER_FACES] of facetype;
  48.     cbuffer : array[0..NUMBER_COORDS*2-1] of integer;
  49.  
  50.     sinustabel : array[0..639] of integer;
  51.     v1,v2,v3 : word; {angle of x,y,z axis}
  52.     cos1,sin1,cos2,sin2,cos3,sin3 : integer;
  53.  
  54.     xkoord,ykoord,zkoord,
  55.     n : integer;
  56.  
  57.     buffer : pScreen;
  58.  
  59.  
  60. CONST
  61.     display1 : word = $0000;
  62.     display2 : word = $4000;
  63.     display3 : word = $8000;
  64.     {coordinates for box}
  65.     coords : array[0..NUMBER_COORDS*3-1] of integer =
  66.         (box,box,-box, -box,box,-box, -box,-box,-box, box,-box,-box,
  67.         box,box,box, -box,box,box, -box,-box,box, box,-box,box);
  68.  
  69.  
  70.  
  71. (*------------------------------------------------*)
  72.  
  73. procedure SetupSinus;
  74. var
  75.     i : integer;
  76.     v, vadd : real;
  77. begin
  78.     v:=0.0;
  79.     vadd:=(2.0*pi/512.0);
  80.     for i:=0 to 639 do begin
  81.         sinustabel[i]:=round(sin(v)*32767);
  82.         v:=v+vadd;
  83.     end;
  84. end;
  85.  
  86. procedure SetupFaces;
  87. begin
  88.     with face[1] do begin l1:=3; l2:=2; l3:=0; l4:=1; end;
  89.     with face[2] do begin l1:=4; l2:=5; l3:=7; l4:=6; end;
  90.     with face[3] do begin l1:=0; l2:=1; l3:=4; l4:=5; end;
  91.     with face[4] do begin l1:=1; l2:=2; l3:=5; l4:=6; end;
  92.     with face[5] do begin l1:=2; l2:=3; l3:=6; l4:=7; end;
  93.     with face[6] do begin l1:=3; l2:=0; l3:=7; l4:=4; end;
  94. end;
  95.  
  96.  
  97. (*------------------------------------------------*)
  98.  
  99. procedure InitDemo;
  100. var
  101.     p : pointer;
  102.     i : integer;
  103. begin
  104.     ClearWholeScreen;
  105.     SetupSinus;
  106.     SetupFaces;
  107.  
  108.     {allocate memory for buffer. Offset MUST be $0000 though!!!}
  109.     New(buffer);
  110.     while Ofs(buffer^)<>0 do begin
  111.         Dispose(buffer);
  112.         GetMem(p,1); {does this really work? Think not!}
  113.         New(buffer);
  114.     end;
  115.     FillChar(buffer^,SizeOf(ScreenType),#0);
  116. end;
  117.  
  118. procedure UninitDemo;
  119. var
  120.     i : integer;
  121. begin
  122.     Dispose(buffer);
  123. end;
  124.  
  125.  
  126. (*------------------------------------------------*)
  127.  
  128. procedure SwapDisplay;
  129. var
  130.     temp : word;
  131. begin
  132.     temp:=display3;
  133.     display3:=display2;
  134.     display2:=display1;
  135.     display1:=temp;
  136.     SetAddress(Ptr(SEGA000,display2));
  137. end;
  138.  
  139. procedure MoveBuffer; assembler;
  140. {Move buffer to display memory}
  141. asm
  142.     push    ds
  143.  
  144.     mov    es,SEGA000
  145.     mov    di,display1
  146.     add    di,(36*40)+12  {center on display screen}
  147.     lds    si,buffer
  148.     xor    ax,ax
  149.     mov    bx,-2
  150.     mov    dx,128            {ysize}
  151.     cld
  152. @yloop:
  153.     mov    cl,8
  154. @xloop:
  155.     movsw                        {move buffer word to video memory}
  156.     mov    [si+bx],ax        {clear the buffer again}
  157.     dec    cl
  158.     jnz    @xloop
  159.  
  160.     add    si,256-16
  161.     add    di,40-16
  162.     dec    dx
  163.     jnz    @yloop
  164.  
  165.     pop    ds
  166. end;
  167.  
  168. (*------------------------------------------------*)
  169.  
  170. procedure CalcAngle;
  171. {Change rotation angle}
  172. begin
  173.     sin1:=sinustabel[v1]; cos1:=sinustabel[v1+128];
  174.     sin2:=sinustabel[v2]; cos2:=sinustabel[v2+128];
  175.     sin3:=sinustabel[v3]; cos3:=sinustabel[v3+128];
  176.     v1:=(v1-1) AND 511;
  177.     v2:=(v2-2) AND 511;
  178.     v3:=(v3+1) AND 511;
  179. end;
  180.  
  181. procedure RotateAllCoords;
  182. var
  183.     i, a,b : integer;
  184.     x,y,z : longint;
  185.     temp : integer;
  186. begin
  187.     a:=0; b:=0;
  188.     for i:=1 to NUMBER_COORDS do begin
  189.         x:=coords[a]; y:=coords[a+1]; z:=coords[a+2];
  190.         inc(a,3);
  191.  
  192.         temp:=y;
  193.         y:=(LongMul(y,cos1) - LongMul(z,sin1)) DIV 32768;
  194.         z:=(LongMul(temp,sin1) + LongMul(z,cos1)) DIV 32768;
  195.         temp:=x;
  196.         x:=(LongMul(x,cos2) + LongMul(z,sin2)) DIV 32768;
  197.         z:=(LongMul(z,cos2) - LongMul(temp,sin2)) DIV 32768;
  198.         temp:=x;
  199.         x:=(LongMul(x,cos3) - LongMul(y,sin3)) DIV 32768;
  200.         y:=(LongMul(temp,sin3) + LongMul(y,cos3)) DIV 32768;
  201.  
  202.         cbuffer[b]:=((x SHL 8) DIV (z+800))+64;
  203.         cbuffer[b+1]:=((y SHL 8) DIV (z+800))+64;
  204.         inc(b,2);
  205.     end;
  206. end;
  207.  
  208.  
  209. function FaceShown(i : integer; l1,l2,l3 : byte) : boolean;
  210. {Is the face turning the back on us?}
  211. var
  212.     a,b : longint;
  213. begin
  214.     a := longmul(cbuffer[l1]-cbuffer[l2],cbuffer[l3+1]-cbuffer[l2+1]);
  215.     b := longmul(cbuffer[l1+1]-cbuffer[l2+1],cbuffer[l3]-cbuffer[l2]);
  216.     FaceShown := (a-b) > 0;
  217. end;
  218.  
  219.  
  220. (*------------------------------------------------*)
  221.  
  222. procedure CalcSlope(x1,y1,x2,y2 : integer; table1,table2 : pointer); assembler;
  223. {Calc points between 2 set of coords}
  224. asm
  225.     DB LONG; xor cx,cx
  226.  
  227.     mov    cx,NUMBER_SPLITS+1 {Split x-line into parts}
  228.     mov    ax,x2
  229.     sub    ax,x1
  230.     DB LONG; shl ax,16
  231.     {cdq} DB $66,$99
  232.     DB LONG; idiv cx
  233.     DB LONG; mov si,ax
  234.     DB LONG; mov dx,ax
  235.     DB LONG; shr dx,16
  236.  
  237.     les    di,table1
  238.     mov    ax,x1
  239.     xor    bx,bx
  240.     mov    cx,NUMBER_SPLITS
  241. @xloop:
  242.     add    bx,si
  243.     adc    ax,dx
  244.     stosw
  245.     dec    cx
  246.     jnz    @xloop
  247.  
  248.     mov    cx,NUMBER_SPLITS+1 {Split y-line into parts}
  249.     mov    ax,y2
  250.     sub    ax,y1
  251.     DB LONG; shl ax,16
  252.     {cdq} DB $66,$99
  253.     DB LONG; idiv cx
  254.     DB LONG; mov si,ax
  255.     DB LONG; mov dx,ax
  256.     DB LONG; shr dx,16
  257.  
  258.     les    di,table2
  259.     mov    ax,y1
  260.     xor    bx,bx
  261.     mov    cx,NUMBER_SPLITS
  262. @yloop:
  263.     add    bx,si
  264.     adc    ax,dx
  265.     stosw
  266.     dec    cx
  267.     jnz    @yloop
  268. end;
  269.  
  270.  
  271. procedure DrawDottedLine(x1,y1,x2,y2 : integer); assembler;
  272. {Draws a line, but splits it up into NUMBER_SPLITS parts and makes
  273.  dots instead}
  274. asm
  275.     mov    cx,NUMBER_SPLITS+1    {break line into n pieces}
  276.  
  277.     mov    ah,BYTE PTR x2
  278.     sub    ah,BYTE PTR x1
  279.     xor    al,al
  280.     cwd
  281.     idiv    cx
  282.     mov    di,ax
  283.  
  284.     mov    ah,BYTE PTR y2
  285.     sub    ah,BYTE PTR y1
  286.     xor    al,al
  287.     cwd
  288.     idiv    cx
  289.     {we need to set AX to BP later, so does mess up AX...}
  290.  
  291.     mov    bh,BYTE PTR x1
  292.     xor    bl,bl
  293.     mov    dh,BYTE PTR y1
  294.     xor    dl,dl
  295.  
  296.     mov    ch,NUMBER_SPLITS
  297.     push    bp
  298.     mov    bp,ax
  299.  
  300.     mov    es,WORD PTR buffer+2
  301.  
  302. @loop:
  303.     add    bx,di        {add to x}
  304.     add    dx,bp        {add to y}
  305.     mov    al,bh
  306.     mov    cl,al        {make a copy of x}
  307.     shr    al,3        {calc x address-offset}
  308.     mov    ah,dh        {get y pos. Since width is 256 bytes, this is easy}
  309.     mov    si,ax
  310.     mov    al,$80    {calc bit pos}
  311.     ror    al,cl
  312.     or        [es:si],al
  313.     dec    ch            {loop. ("dec cx, jnz.." is faster than "LOOP @loop")}
  314.     jnz    @loop
  315.  
  316.     pop    bp
  317. end;
  318.  
  319.  
  320. (*------------------------------------------------*)
  321.  
  322. procedure RunOnce;
  323. var
  324.     i,j : integer;
  325. begin
  326.     SwapDisplay;
  327. {$IFNDEF DEBUG}
  328.     while retraces=0 do ;
  329.     retraces:=0;
  330. {$ELSE}
  331.     VBLANK;
  332.     SetRGB(0,20,0,0);
  333. {$ENDIF}
  334.  
  335.     CalcAngle;
  336.     RotateAllCoords;
  337.  
  338.     for i:=1 to NUMBER_FACES do begin
  339.         with face[i] do if FaceShown(i, l1 shl 1,l2 shl 1,l3 shl 1) then begin
  340.             CalcSlope(cbuffer[(l1 SHL 1)],cbuffer[(l1 SHL 1)+1], cbuffer[(l2 SHL 1)],cbuffer[(l2 SHL 1)+1], @SlopeX1,@SlopeY1);
  341.             CalcSlope(cbuffer[(l3 SHL 1)],cbuffer[(l3 SHL 1)+1], cbuffer[(l4 SHL 1)],cbuffer[(l4 SHL 1)+1], @SlopeX2,@SlopeY2);
  342.             for j:=0 to NUMBER_SPLITS-1 do
  343.                 DrawDottedLine(SlopeX1[j],SlopeY1[j],SlopeX2[j],SlopeY2[j]);
  344.         end;
  345.     end;
  346.  
  347.     MoveBuffer;
  348.  
  349. {$IFDEF DEBUG}
  350.     SetRGB(0,0,0,0);
  351.     while KeyHit[26] do ; {Hit 'P' to pause in debug mode}
  352. {$ENDIF}
  353. end;
  354.  
  355.  
  356. begin
  357.     SetScreenMode($D);
  358.     Screen_Off;
  359.     InitDemo;
  360.     Screen_On;
  361.     SetAllInterrupts;
  362.     repeat RunOnce until Key='e'; {press ESCape key to exit}
  363.     RestoreAllInterrupts;
  364.     UninitDemo;
  365.     SetScreenMode(TEXTMODE);
  366. end.
  367.